#include <stdexcept>
#include <vector>

#include "gl_texture.h"

using namespace eqClient;

GLenum const TextureBinding::tex2enum[] = {
    GL_TEXTURE0,
    GL_TEXTURE1,
    GL_TEXTURE2,
    GL_TEXTURE3,
    GL_TEXTURE4,
    GL_TEXTURE5,
    GL_TEXTURE6,
    GL_TEXTURE7,
};

GLTexture::GLTexture(GLEWContext const* context):
GLEWContextHolder(context),
texture()
{
    allocateDefault();
}

GLTexture::GLTexture(GLenum internalFormat, GLsizei width, GLsizei height, GLEWContext const* context):
GLEWContextHolder(context),
texture()
{
    allocateDefault();
    assign(internalFormat, width, height);
}

GLTexture::~GLTexture()
{
    if(texture != 0)
        glDeleteTextures(1, &texture);
}

void GLTexture::assign(GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* data)
{
    TextureBinding binding(*this);
    
    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, data);
    
    glGenerateMipmap(GL_TEXTURE_2D);
}

void GLTexture::assign(GLenum internalFormat, GLsizei width, GLsizei height)
{
    GLenum format = GL_LUMINANCE;
    GLenum type = GL_UNSIGNED_BYTE;
    std::vector<GLubyte> buffer(height * ((width + 3) / 4 * 4));
    assign(internalFormat, width, height, format, type, buffer.data());
}

void GLTexture::allocateDefault()
{
    texture = 0;
    glGenTextures(1, &texture);
    if(texture == 0)
        throw std::runtime_error("Texture object allocation failed.");
    
    TextureBinding binding(*this);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
